package com.tjh.springbootapi.webSocket.service;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * Create by koala on 2022-08-14
 */
@Slf4j
public class NioWebSocketServer implements Runnable {

    protected String host;

    protected int port;

    public NioWebSocketServer(int port) {
        this.port = port;
    }

    @Override
    public void run() {
        log.info("正在启动websocket服务器");
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup work = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boss, work);
            bootstrap.channel(NioServerSocketChannel.class);
            if (StringUtils.isNotBlank(host)) {
                bootstrap.localAddress(host, port);
            } else {
                bootstrap.localAddress(port);
            }

            bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    //设置log监听器，并且日志级别为debug，方便观察运行流程
                    socketChannel.pipeline().addLast("logging", new LoggingHandler("DEBUG"));
                    //设置解码器
                    socketChannel.pipeline().addLast("http-codec", new HttpServerCodec());
                    //聚合器，使用websocket会用到
                    socketChannel.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));
                    //用于大数据的分区传输
                    socketChannel.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
                    //自定义的业务handler
                    socketChannel.pipeline().addLast("handler", new NioWebSocketHandler());
                }
            });

            bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture cf = bootstrap.bind().sync();
            log.info("webSocket服务器启动成功：" + cf.channel());
            cf.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
            log.info("运行出错：" + e);
        } finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
            log.info("websocket服务器已关闭");
        }
    }
}